<?php

namespace Plugins\ApiDoc\Http\Api\Controller;

use App\Middlewares\Api\ApiAuthenticateMiddleware;
use App\Middlewares\Api\ApiTokenSetMiddleware;
use App\Util\Response;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\PostMapping;
use Plugins\ApiDoc\Attributes\Api;
use Plugins\ApiDoc\Attributes\ApiBody;
use Plugins\ApiDoc\Attributes\ApiQuery;
use Plugins\ApiDoc\Attributes\ApiReturn;
use Plugins\ApiDoc\Attributes\ApiVersion;
use Psr\Http\Message\ResponseInterface;
use Sc\Util\Tool;

/**
 * API文档demo
 * 1、一个控制器为一组接口，
 * 2、注释的第一行文本为接口的名称
 *
 * Class ApiDocDemo
 */
#[Api]
#[Controller('doc-demo')]
class DemoController
{
    /**
     * 测试GET请求
     *
     */
    #[Api]
    #[ApiQuery('id', 'Integer', 'ID', true)]
    #[ApiReturn('id', 'Integer', 'ID')]
    #[ApiReturn('title', 'String', '标题')]
    #[ApiReturn('describe', 'String', '描述')]
    #[GetMapping(path: 'get-demo')]
    public function get(): ResponseInterface
    {
        $query = ['id' => 1];

        return Response::json()->success([
            'id'       => 1,
            'title'    => '标题',
            'describe' => '介绍',
        ]);
    }

    /**
     * 测试POST请求
     *
     * @return ResponseInterface
     */
    #[Api]
    #[ApiBody('id', 'Integer', 'ID', true)]
    #[ApiBody('array', 'Array', '数组', true)]
    #[ApiBody('arrayObject', 'Array', '包含对象的数组')]
    #[ApiBody('arrayObject.field1', 'String', '字段一')]
    #[ApiBody('arrayObject.field2', 'String', '字段二')]
    #[ApiBody('arrayObject.field3', 'String', '字段三')]
    #[ApiBody('Object', 'Object', '对象')]
    #[ApiBody('Object.field1', 'String', '字段一')]
    #[ApiBody('Object.field2', 'String', '字段二')]
    #[ApiBody('Object.field3', 'String', '字段三')]
    #[ApiBody('file', 'File', '文件上传')]
    #[ApiReturn('id', 'Integer', 'ID')]
    #[ApiReturn('title', 'String', '标题')]
    #[ApiReturn('describe', 'String', '描述')]
    #[PostMapping(path: 'post-demo')]
    public function post(): ResponseInterface
    {
        $post = [
            'id' => 1,
            'array' => [1,2,3,4],
            'arrayObject' => [
                [
                    'field1' => '',
                    'field2' => '',
                    'field3' => '',
                ]
            ],
            'Object' => [
                'field1' => '',
                'field2' => '',
                'field3' => '',
            ],
            'file' => "文件地址",
        ];

        return Response::json()->success([
            'id'       => 1,
            'title'    => '标题',
            'describe' => '介绍',
        ]);
    }

    /**
     * 返回数据示例
     *
     * @return ResponseInterface
     */
    #[Api]
    #[ApiReturn('id', 'Integer', 'ID', true)]
    #[ApiReturn('demoArr', 'Array', '数组', true)]
    #[ApiReturn('demoArr.id', 'Integer', '数组ID', true)]
    #[ApiReturn('demoArr.title', 'String', '数组标题', true)]
    #[ApiReturn('demoArr.des', 'String', '数组介绍', true)]
    #[ApiReturn('demoObj', 'Object', '对象', true)]
    #[ApiReturn('demoObj.id', 'Integer', '对象ID', true)]
    #[ApiReturn('demoObj.title', 'String', '对象标题', true)]
    #[ApiReturn('demoObj.des', 'String', '对象介绍', true)]
    #[GetMapping(path: 'return-demo')]
    public function return(): ResponseInterface
    {
        return Response::json()->success([
            'id' => 1,
            'demoArr' => [
                [
                    'id'    => 1,
                    'title' => '标题',
                    'des'   => '介绍',
                ],
                [
                    'id'    => 2,
                    'title' => '标题2',
                    'des'   => '介绍2',
                ],
            ],
            'demoObj' => [
                'id'    => 1,
                'title' => '标题',
                'des'   => '介绍',
            ]
        ]);
    }

    /**
     * 版本示例
     *
     * @return ResponseInterface
     */
    #[Api(true)]
    #[ApiQuery('id', 'Integer', 'ID', true, 2)]
    #[ApiQuery('ids', 'Float', 'ID', true, -2)]
    #[ApiQuery('idb', 'String', 'IDS', true)]
    #[ApiReturn('id', 'Integer', 'ID', true, 2)]
    #[ApiReturn('ids', 'Array', 'IDS', true, -2)]
    #[ApiReturn('idb', 'String', 'IDS', true)]
    #[ApiVersion(1, '基础版本，只有一个版本时，可不使用')]
    #[ApiVersion(2, '增加版本介绍')]
    #[GetMapping(path: 'version-demo')]
    public function version(): ResponseInterface
    {
        return Response::json()->success([
            'id'  => 1,
            'idb' => 'idb',
        ]);
    }

    /**
     * 认证示例
     *  需要用户认证的接口
     *  #[Api(true)] 给Api参数true
     *  或设置中间件 ApiAuthenticateMiddleware 都可以实现文档认证的标识，但是代码实现认证必须使用中间件方式
     *  没有设置中间件的标识时该接口不是强制要求认证
     * @return ResponseInterface
     */
    #[Api(true)]
    #[GetMapping(path: 'authenticate-demo')]
    #[Middlewares([ApiTokenSetMiddleware::class, ApiAuthenticateMiddleware::class])]
    public function authenticate(): ResponseInterface
    {
        return Response::json()->success();
    }

    /**
     * 登录示例
     *
     */
    #[Api]
    #[ApiBody('account', 'String', '账号')]
    #[ApiBody('password', 'String', '密码')]
    #[ApiReturn('user', 'Object', '用户信息')]
    #[ApiReturn('user.name', 'String', '用户名')]
    #[ApiReturn('user.age', 'Integer', '年龄')]
    #[ApiReturn('user.avatar', 'String', '头像')]
    #[ApiReturn('user.sex', 'String', '性别')]
    #[ApiReturn('token', 'Object', 'Token')]
    #[ApiReturn('token.token', 'String', 'Token')]
    #[ApiReturn('token.token_exp', 'Integer', 'Token过期时间')]
    #[PostMapping(path: 'login-demo')]
    public function login(): ResponseInterface
    {
        return Response::json()->success([
            'user'  => [
                'name'   => 'test',
                'age'    => 18,
                'avatar' => 'https://test.test.com',
                'sex'    => '男',
            ],
            'token' => Tool::jwt()->setData(['user_id' => 1])->getToken()
        ]);
    }

    /**
     * 刷新token数据返回示例，实际程序会自动处理无需手动请求
     *
     * @return ResponseInterface
     */
    #[Api]
    #[ApiReturn('token', 'Object', 'Token')]
    #[ApiReturn('token.token', 'String', 'Token')]
    #[ApiReturn('token.token_exp', 'Integer', 'Token过期时间')]
    #[GetMapping(path: 'refresh-token-demo')]
    public function refreshToken(): ResponseInterface
    {
        return Response::json()->body(Tool\JWT::EXPIRE_CODE, "token过期 自动刷新", [
            'token' => Tool::jwt()->setData(['user_id' => 1])->getToken()
        ]);
    }
}